package com.pig4cloud.pig.admin.controller;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.pig4cloud.pig.admin.api.entity.PrDeviceEntity;
import com.pig4cloud.pig.admin.api.entity.PrUserEntity;
import com.pig4cloud.pig.admin.api.entity.PrUserRfidInfoEntity;
import com.pig4cloud.pig.admin.api.entity.SysUser;
import com.pig4cloud.pig.admin.api.vo.UserVO;
import com.pig4cloud.pig.admin.emqx.dto.EmqxClientQueryDto;
import com.pig4cloud.pig.admin.emqx.openapi.EmqxFeignClient;
import com.pig4cloud.pig.admin.emqx.vo.EmqxDataVo;
import com.pig4cloud.pig.admin.emqx.vo.MqttClientStats;
import com.pig4cloud.pig.admin.mapper.PrUserMapper;
import com.pig4cloud.pig.admin.mapper.SysUserMapper;
import com.pig4cloud.pig.admin.mq.MqttMessageSender;
import com.pig4cloud.pig.admin.mq.vo.SendRequestVo;
import com.pig4cloud.pig.admin.mq.vo.UpdateUserVo;
import com.pig4cloud.pig.admin.service.PrDeviceService;
import com.pig4cloud.pig.admin.service.PrUserService;
import com.pig4cloud.pig.admin.service.SysUserService;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.log.annotation.SysLog;
import com.pig4cloud.plugin.excel.annotation.RequestExcel;
import com.pig4cloud.plugin.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

import static java.util.Collections.unmodifiableMap;

/**
 * 柜体用户信息
 *
 * @author pig
 * @date 2025-08-02 11:35:56
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/prUser" )
@Tag(description = "prUser" , name = "柜体用户信息管理" )
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class PrUserController {

    private final  PrUserService prUserService;
    private final PrDeviceService prDeviceService;
    private final PrUserMapper prUserMapper;
	private final SysUserService sysUserService;
	private final SysUserMapper sysUserMapper;
	private final MqttMessageSender mqttMessageSender;
	@Value("${spring.mqtt.devTopic}")
	private String devTopic;
	@Resource
	private EmqxFeignClient emqFeignClient;

    /**
     * 分页查询
     * @param page 分页对象
     * @param prUser 柜体用户信息
     * @return
     */
    @Operation(summary = "分页查询" , description = "分页查询" )
    @GetMapping("/page" )
    @PreAuthorize("@pms.hasPermission('admin_prUser_view')" )
    public R getPrUserPage(@ParameterObject Page<PrUserEntity> page, @ParameterObject PrUserEntity prUser) {
        LambdaQueryWrapper<PrUserEntity> wrapper = Wrappers.lambdaQuery();
		wrapper.eq(StrUtil.isNotBlank(prUser.getRealName()),PrUserEntity::getRealName,prUser.getRealName());
		wrapper.eq(StrUtil.isNotBlank(prUser.getUserName()),PrUserEntity::getUserName,prUser.getUserName());
		wrapper.eq(StrUtil.isNotBlank(prUser.getIsAdmin()),PrUserEntity::getIsAdmin,prUser.getIsAdmin());
		wrapper.eq(StrUtil.isNotBlank(prUser.getTelephone()),PrUserEntity::getTelephone,prUser.getTelephone());
		wrapper.eq(null != prUser.getDeviceId(),PrUserEntity::getDeviceId,prUser.getDeviceId());

		Page<PrUserEntity> rtPage = prUserService.page(page, wrapper);
		//当前设备是否在线
		EmqxClientQueryDto emqxClientQueryDto = new EmqxClientQueryDto();
		EmqxDataVo<MqttClientStats> mqttClientStats = emqFeignClient.getMqttClientStats(emqxClientQueryDto);
		List<String> clientIdList = mqttClientStats.getData().stream().filter(MqttClientStats::getConnected).map(MqttClientStats::getClientid).collect(Collectors.toList());

		rtPage.getRecords().forEach(rt -> {
			if(clientIdList.contains(rt.getDeviceSign())){
				rt.setOnline("在线");
				rt.setEnabled(Boolean.TRUE);
			}else{
				rt.setOnline("离线");
				rt.setEnabled(Boolean.FALSE);
			}
		});
        return R.ok(rtPage);
    }
	/**
	 * 分页查询 绑定状态
	 * @param prUser 柜体用户信息
	 * @return
	 */
	@Operation(summary = "分页查询" , description = "分页查询" )
	@GetMapping("/page/bind" )
	@PreAuthorize("@pms.hasPermission('admin_prUser_view')" )
	public R getPrUserPageBind(@ParameterObject PrUserEntity prUser) {
		MPJLambdaWrapper<PrUserEntity> wrapper = new MPJLambdaWrapper<PrUserEntity>()
				.selectAll(PrUserEntity.class)
				.selectCollection(PrUserRfidInfoEntity.class, PrUserEntity::getPrUserRfidInfoEntities)
				.leftJoin(PrUserRfidInfoEntity.class,
						on -> {
							on.eq(PrUserRfidInfoEntity::getUserId, PrUserEntity::getUserId);
							on.eq(PrUserRfidInfoEntity::getGoodsId,prUser.getGoodsId());
							return on;
						});
		wrapper.eq(null != prUser.getDeviceSign(), PrUserEntity::getDeviceSign, prUser.getDeviceSign());
		JSONObject jsonObject = new  JSONObject();
		jsonObject.put("records", prUserMapper.selectJoinList(PrUserEntity.class,wrapper));
		return R.ok(jsonObject);
	}

	/**
	 * 分组用户
	 * @return
	 */
	@GetMapping("/group/device")
	public R groupDevice(){
		List<PrUserEntity> prUserEntities = prUserService.list();
		//组织设备名称与sign的映射
		Map<String, String> userMap = prUserEntities.stream().collect(Collectors.toMap(PrUserEntity::getDeviceSign, PrUserEntity::getDeviceName,(o,r)->{return o;}));
		List<Map<String, Object>> collect = prUserEntities.stream()
				.collect(Collectors.groupingBy(
						PrUserEntity::getDeviceSign,
						Collectors.mapping(user -> {
							Map<String, Object> map = new HashMap<>();
							map.put("label", user.getUserName());
							map.put("value", user.getUserId());
							return unmodifiableMap(map);
						}, Collectors.toList())
				))
				.entrySet().stream()
				.map(entry -> {
					Map<String, Object> node = new HashMap<>();
					node.put("label", userMap.get(entry.getKey()));
					node.put("value", entry.getKey());
					node.put("children", entry.getValue());
					return unmodifiableMap(node);
				})
				.collect(Collectors.toList());
		return R.ok(collect);
	}
    /**
     * 通过条件查询柜体用户信息
     * @param prUser 查询条件
     * @return R  对象列表
     */
    @Operation(summary = "通过条件查询" , description = "通过条件查询对象" )
    @GetMapping("/details" )
    @PreAuthorize("@pms.hasPermission('admin_prUser_view')" )
    public R getDetails(@ParameterObject PrUserEntity prUser) {
        return R.ok(prUserService.list(Wrappers.query(prUser)));
    }

    /**
     * 新增柜体用户信息
     * @param prUser 柜体用户信息
     * @return R
     */
    @Operation(summary = "新增柜体用户信息" , description = "新增柜体用户信息" )
    @SysLog("新增柜体用户信息" )
    @PostMapping
    @PreAuthorize("@pms.hasPermission('admin_prUser_add')" )
    public R save(@RequestBody PrUserEntity prUser) {
		//获取柜体信息
		PrDeviceEntity prDeviceEntity = prDeviceService.getById(prUser.getDeviceId());

		//当前设备是否在线
		EmqxClientQueryDto emqxClientQueryDto = new EmqxClientQueryDto();
		EmqxDataVo<MqttClientStats> mqttClientStats = emqFeignClient.getMqttClientStats(emqxClientQueryDto);
		List<String> clientIdList = mqttClientStats.getData().stream().filter(MqttClientStats::getConnected).map(MqttClientStats::getClientid).collect(Collectors.toList());
		if(!clientIdList.contains(prDeviceEntity.getDevSign())){
			return R.result(null,500,"当前设备不在线");
		}

		prUser.setDeviceName(prDeviceEntity.getName());
		prUser.setDeviceSign(prDeviceEntity.getDevSign());

		//给柜体发送添加用户请求
		//获取设备sign
		SendRequestVo<UpdateUserVo> sendRequestVo = new SendRequestVo<UpdateUserVo>();
		UpdateUserVo updateRfidVo = new UpdateUserVo();
		//用户id
		String addUserId = prUser.getDeviceSign() + UUID.randomUUID()
				.toString()
				.replace("-", "")
				.substring(0, 12);
		updateRfidVo.setUserId(addUserId);
		updateRfidVo.setUserName(prUser.getUserName());
		updateRfidVo.setPassword(prUser.getPassword());
		updateRfidVo.setRealName(prUser.getRealName());
		updateRfidVo.setIsAdmin(prUser.getIsAdmin());
		updateRfidVo.setTelephone(prUser.getTelephone());
		//获取当前用户绑定的柜体用户
		JSONArray jsonUser = jsonUserInfo();
		if(null == jsonUser){
			return R.failed("当前用户未绑定柜体");
		}
		String userId = "";
		userId = getUserId(prUser, jsonUser, userId);
		updateRfidVo.setManagerUserId(userId);
		sendRequestVo.setData(updateRfidVo);
		sendRequestVo.setDeviceid(prUser.getDeviceSign());
		sendRequestVo.setType("send");
		sendRequestVo.setCmdtype("06");
		String tic = String.format(devTopic, prUser.getDeviceSign());
		mqttMessageSender.send(prUser.getDeviceSign(),tic,0, JSONObject.toJSONString(sendRequestVo));

		return R.ok();
    }

	private JSONArray jsonUserInfo() {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(SysUser::getUsername, authentication.getName());
		SysUser user = sysUserService.getOne(queryWrapper);
		UserVO userVO = sysUserMapper.getUserVoById(user.getUserId());
		JSONArray jsonUser = userVO.getPrUser();
		return jsonUser;
	}

	private static String getUserId(PrUserEntity prUser, JSONArray jsonUser, String userId) {
		for (int i = 0; i < jsonUser.size(); i++) {
			JSONArray pu = jsonUser.getJSONArray(i);
			String deviceSign = pu.getString(0);
			if(prUser.getDeviceSign().equals(deviceSign)){
				userId = pu.getString(1);
			}

		}
		return userId;
	}

	/**
     * 修改柜体用户信息
     * @param prUser 柜体用户信息
     * @return R
     */
    @Operation(summary = "修改柜体用户信息" , description = "修改柜体用户信息" )
    @SysLog("修改柜体用户信息" )
    @PutMapping
    @PreAuthorize("@pms.hasPermission('admin_prUser_edit')" )
    public R updateById(@RequestBody PrUserEntity prUser) {
		//获取柜体信息
		PrDeviceEntity prDeviceEntity = prDeviceService.getById(prUser.getDeviceId());

		//当前设备是否在线
		EmqxClientQueryDto emqxClientQueryDto = new EmqxClientQueryDto();
		EmqxDataVo<MqttClientStats> mqttClientStats = emqFeignClient.getMqttClientStats(emqxClientQueryDto);
		List<String> clientIdList = mqttClientStats.getData().stream().filter(MqttClientStats::getConnected).map(MqttClientStats::getClientid).collect(Collectors.toList());
		if(!clientIdList.contains(prDeviceEntity.getDevSign())){
			return R.result(null,500,"当前设备不在线");
		}

		prUser.setDeviceName(prDeviceEntity.getName());
		prUser.setDeviceSign(prDeviceEntity.getDevSign());

		//给柜体发送修改请求
		//给柜体发送添加用户请求
		//获取设备sign
		SendRequestVo<UpdateUserVo> sendRequestVo = new SendRequestVo<UpdateUserVo>();
		UpdateUserVo updateRfidVo = new UpdateUserVo();
		updateRfidVo.setUserId(prUser.getUserId());
		updateRfidVo.setUserName(prUser.getUserName());
		updateRfidVo.setPassword(prUser.getPassword());
		updateRfidVo.setRealName(prUser.getRealName());
		updateRfidVo.setIsAdmin(prUser.getIsAdmin());
		updateRfidVo.setTelephone(prUser.getTelephone());
		//获取当前用户绑定的柜体用户
		JSONArray jsonUser = jsonUserInfo();
		if(null == jsonUser){
			return R.failed("当前用户未绑定柜体");
		}
		String userId = "";
		userId = getUserId(prUser, jsonUser, userId);
		updateRfidVo.setManagerUserId(userId);
		sendRequestVo.setData(updateRfidVo);
		sendRequestVo.setDeviceid(prUser.getDeviceSign());
		sendRequestVo.setType("send");
		sendRequestVo.setCmdtype("07");
		String tic = String.format(devTopic, prUser.getDeviceSign());
		mqttMessageSender.send(prUser.getDeviceSign(),tic,0, JSONObject.toJSONString(sendRequestVo));

        return R.ok();
    }

    /**
     * 通过id删除柜体用户信息
     * @param ids id列表
     * @return R
     */
    @Operation(summary = "通过id删除柜体用户信息" , description = "通过id删除柜体用户信息" )
    @SysLog("通过id删除柜体用户信息" )
    @DeleteMapping
    @PreAuthorize("@pms.hasPermission('admin_prUser_del')" )
    public R removeById(@RequestBody Integer[] ids) {

		//当前操作的用户id
		//获取当前用户绑定的柜体用户
		JSONArray jsonUser = jsonUserInfo();
		if(null == jsonUser){
			return R.failed("当前用户未绑定柜体");
		}
		String userId = "";

		for (Integer id : ids) {
			//获取柜体用户id
			PrUserEntity prUserEntity = prUserService.getById(id);

			//当前设备是否在线
			EmqxClientQueryDto emqxClientQueryDto = new EmqxClientQueryDto();
			EmqxDataVo<MqttClientStats> mqttClientStats = emqFeignClient.getMqttClientStats(emqxClientQueryDto);
			List<String> clientIdList = mqttClientStats.getData().stream().filter(MqttClientStats::getConnected).map(MqttClientStats::getClientid).collect(Collectors.toList());
			if(!clientIdList.contains(prUserEntity.getDeviceSign())){
				return R.result(null,500,"当前设备不在线");
			}


			userId = getUserId(prUserEntity, jsonUser, userId);
			SendRequestVo<UpdateUserVo> sendRequestVo = new SendRequestVo<UpdateUserVo>();
			UpdateUserVo updateRfidVo = new UpdateUserVo();
			updateRfidVo.setUserId(prUserEntity.getUserId());
			updateRfidVo.setManagerUserId(userId);
			sendRequestVo.setDeviceid(prUserEntity.getDeviceSign());
			sendRequestVo.setType("send");
			sendRequestVo.setCmdtype("08");
			sendRequestVo.setData(updateRfidVo);
			String tic = String.format(devTopic, prUserEntity.getDeviceSign());
			//更新系统用户绑定状态
			QueryWrapper<SysUser> sysUserQueryWrapper = new QueryWrapper<>();
			sysUserQueryWrapper.lambda().like(SysUser::getPrUser,prUserEntity.getUserId());
			List<SysUser> list = sysUserService.list(sysUserQueryWrapper);
			list.forEach(sysUser -> {sysUser.setPrUser(null);});
			sysUserService.updateBatchById(list);
			mqttMessageSender.send(prUserEntity.getDeviceSign(),tic,0, JSONObject.toJSONString(sendRequestVo));

		}

        return R.ok();
    }


    /**
     * 导出excel 表格
     * @param prUser 查询条件
   	 * @param ids 导出指定ID
     * @return excel 文件流
     */
    @ResponseExcel
    @GetMapping("/export")
    @PreAuthorize("@pms.hasPermission('admin_prUser_export')" )
    public List<PrUserEntity> exportExcel(PrUserEntity prUser,Integer[] ids) {
        return prUserService.list(Wrappers.lambdaQuery(prUser).in(ArrayUtil.isNotEmpty(ids), PrUserEntity::getId, ids));
    }

    /**
     * 导入excel 表
     * @param prUserList 对象实体列表
     * @param bindingResult 错误信息列表
     * @return ok fail
     */
    @PostMapping("/import")
    @PreAuthorize("@pms.hasPermission('admin_prUser_export')" )
    public R importExcel(@RequestExcel List<PrUserEntity> prUserList, BindingResult bindingResult) {
        return R.ok(prUserService.saveBatch(prUserList));
    }
}
